package com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.bean.LimsQualitycontrolTestResultBean;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.bean.LimsQualitycontrolTestResultManageBean;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.bean.LimsQualitycontrolTestResultManageSaveBean;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.dao.LimsQualitycontrolTestResultManageDao;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.service.LimsQualitycontrolTestResultManageSaveService;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.service.LimsQualitycontrolTestResultManageService;
import com.sunwayworld.basemodule.business.qualitycontrol.qualitycontrolresult.service.LimsQualitycontrolTestResultService;
import com.sunwayworld.basemodule.business.qualitycontrol.qualityrule.bean.LimsQualityRuleBean;
import com.sunwayworld.basemodule.business.qualitycontrol.qualityrule.service.LimsQualityRuleService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.data.page.Page;
import com.sunwayworld.framework.data.page.Pagination;
import com.sunwayworld.framework.exception.UnsupportedException;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.mybatis.page.MybatisPageHelper;
import com.sunwayworld.framework.mybatis.page.PageRowBounds;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.PersistableHelper;
import com.sunwayworld.framework.utils.BeanUtils;
import com.sunwayworld.framework.utils.ClassUtils;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsQualitycontrolTestResultManageServiceImpl implements LimsQualitycontrolTestResultManageService {

    @Autowired
    private LimsQualitycontrolTestResultManageDao limsQualitycontrolTestResultManageDao;

    @Autowired
    private LimsQualityRuleService limsQualityRuleService;

    @Autowired
    private LimsQualitycontrolTestResultManageSaveService limsQualitycontrolTestResultManageSaveService;

    @Autowired
    @Lazy
    private LimsQualitycontrolTestResultService limsQualitycontrolTestResultService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsQualitycontrolTestResultManageDao getDao() {
        return limsQualitycontrolTestResultManageDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsQualitycontrolTestResultManageBean limsQualitycontrolTestResultManage = jsonWrapper.parseUnique(LimsQualitycontrolTestResultManageBean.class);
        limsQualitycontrolTestResultManage.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsQualitycontrolTestResultManage);
        return limsQualitycontrolTestResultManage.getId();
    }

    @Override
    public <V> Page<LimsQualitycontrolTestResultManageBean> selectPagination(Supplier<List<V>> mapOrItemSupplier, PageRowBounds rowBounds) {
        Page<V> page = MybatisPageHelper.get(rowBounds, mapOrItemSupplier);

        if (page.getRows().isEmpty()) {
            return new Pagination<>(page, CollectionUtils.emptyList());
        }

        Class<V> clazz = (Class<V>) ClassUtils.getRawType(page.getRows().get(0).getClass());

        if (Map.class.isAssignableFrom(clazz)) {
            List<LimsQualitycontrolTestResultManageBean> itemList = page.getRows().parallelStream().map(m -> PersistableHelper.mapToPersistable((Map<String, Object>) m, getDao().getType())).collect(Collectors.toList());
            itemList.forEach(i -> {
                if (i.getControlRule() != null) {
                    List<String> controlRuleIds = Arrays.asList(i.getControlRule().split(","));

                    List<LimsQualityRuleBean> ruleBeanList = limsQualityRuleService.selectListByFilter(SearchFilter.instance().match("id", controlRuleIds).filter(MatchPattern.OR));
                    if (!ruleBeanList.isEmpty()) {
                        Collections.sort(ruleBeanList);
                        String controlRuleName = StringUtils.join(ruleBeanList.stream().map(LimsQualityRuleBean::getRuleName).collect(Collectors.toList()), ",");
                        i.setExt$Item("controlrulename", controlRuleName);
                    } else {
                        i.setExt$Item("controlrulename", "");
                    }
                }
            });
            return new Pagination<>(page, itemList);
        } else if (getDao().getType().isAssignableFrom(clazz)) {
            return (Page<LimsQualitycontrolTestResultManageBean>) page;
        }

        throw new UnsupportedException();
    }

    @Override
    public Page<LimsQualitycontrolTestResultManageBean> selectDistinctRowsByCondition(RestJsonWrapperBean wrapper) {
        MapperParameter parameter = wrapper.extractMapFilter();
        PageRowBounds rowBounds = wrapper.extractPageRowBounds();
        return this.selectDistinctRows_(parameter, rowBounds);
    }

    @Override
    public JSONObject saveToManageSaveTable(RestJsonWrapperBean wrapper) {
        String createdById = wrapper.getParamValue("createdById");
        Long groupByCreaterAndId = Long.valueOf(wrapper.getParamValue("groupByCreaterAndId"));
        JSONObject req = new JSONObject();

        List<LimsQualitycontrolTestResultManageBean> data = selectListByFilter(
                SearchFilter.instance().match("createdById", createdById).filter(MatchPattern.EQ)
                        .match("groupByCreaterAndId", groupByCreaterAndId).filter(MatchPattern.EQ));

        List<LimsQualitycontrolTestResultManageSaveBean> saveData = limsQualitycontrolTestResultManageSaveService.selectListByFilter(
                SearchFilter.instance().match("createdById", createdById).filter(MatchPattern.EQ)
                        .match("groupByCreaterAndId", groupByCreaterAndId).filter(MatchPattern.EQ));

        if (!data.isEmpty() && saveData.isEmpty()) {
            List<LimsQualitycontrolTestResultManageSaveBean> insertList = new ArrayList<>();
            data.forEach(i -> {
                LimsQualitycontrolTestResultManageSaveBean insertBean = new LimsQualitycontrolTestResultManageSaveBean();
                BeanUtils.copyProperties(i, insertBean);
                insertBean.setId(ApplicationContextHelper.getNextIdentity());
                insertList.add(insertBean);
            });
            limsQualitycontrolTestResultManageSaveService.getDao().insert(insertList);
        }

        if (!data.isEmpty() && !saveData.isEmpty()) {
            List<Long> delIds = saveData.stream().map(LimsQualitycontrolTestResultManageSaveBean::getId).collect(Collectors.toList());
            limsQualitycontrolTestResultManageSaveService.getDao().deleteByIdList(delIds);

            List<LimsQualitycontrolTestResultManageSaveBean> insertList = new ArrayList<>();
            data.forEach(i -> {
                LimsQualitycontrolTestResultManageSaveBean insertBean = new LimsQualitycontrolTestResultManageSaveBean();
                BeanUtils.copyProperties(i, insertBean);
                insertBean.setId(ApplicationContextHelper.getNextIdentity());
                insertList.add(insertBean);
            });
            limsQualitycontrolTestResultManageSaveService.getDao().insert(insertList);
        }

        return req;
    }

    @Override
    public JSONObject setRemoveStatus(RestJsonWrapperBean wrapperBean) {
        JSONObject req = new JSONObject();

        String removeStatus = wrapperBean.getParamValue("removeStatus");

        List<LimsQualitycontrolTestResultManageBean> manageBeans = wrapperBean.parse(LimsQualitycontrolTestResultManageBean.class);
        List<Long> manageBeanIds = manageBeans.stream().map(LimsQualitycontrolTestResultManageBean::getId).collect(Collectors.toList());
        List<Long> resultIds = manageBeans.stream().map(LimsQualitycontrolTestResultManageBean::getResultId).collect(Collectors.toList());

        LimsQualitycontrolTestResultManageBean updateBeanManage = new LimsQualitycontrolTestResultManageBean();
        updateBeanManage.setRemoveStatus(removeStatus);
        getDao().updateByIds(updateBeanManage, manageBeanIds, "removeStatus");

        LimsQualitycontrolTestResultBean updateBeanResult = new LimsQualitycontrolTestResultBean();
        updateBeanResult.setRemoveStatus(removeStatus);
        limsQualitycontrolTestResultService.getDao().updateByIds(updateBeanResult, resultIds, "removeStatus");

        return req;
    }

    Page<LimsQualitycontrolTestResultManageBean> selectDistinctRows_(MapperParameter parameter, PageRowBounds rowBounds) {
        Page<Map<String, Object>> pageMap = MybatisPageHelper.get(rowBounds, () -> getDao().selectDistinctRowsByCondition(parameter));
        if (pageMap.getRows().isEmpty()) {
            return new Pagination<LimsQualitycontrolTestResultManageBean>();
        }
        List<LimsQualitycontrolTestResultManageBean> results = pageMap.getRows().stream().map(m -> PersistableHelper.mapToPersistable(m, LimsQualitycontrolTestResultManageBean.class)).collect(Collectors.toList());

        DecimalFormat decimalFormat = new DecimalFormat("#.000");
        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);// 保留三位小数时，四舍五入
        results.forEach(i -> {
            double averageForHistory = limsQualitycontrolTestResultService.selectAverageForHistory(i.getMainBatchCode(), i.getControlMaterialLevel(), i.getProductName());
            double sDForHistory = limsQualitycontrolTestResultService.selectSDForHistory(i.getMainBatchCode(), i.getControlMaterialLevel(), i.getProductName());
            i.setExt$Item("averageforhistory", String.valueOf(averageForHistory));
            i.setExt$Item("sdforhistory", String.valueOf(sDForHistory));
            i.setExt$Item("cvforhistory", decimalFormat.format(sDForHistory / averageForHistory * 100d));
        });

        return new Pagination<LimsQualitycontrolTestResultManageBean>(pageMap, results);
    }
}
